#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace Weazel.Gezel.Simulator.Reference
{
  /// <summary>
  /// The sequence controller executes one or more
  /// datapath instructions in a round robin fashion
  /// </summary>
  class SequenceController : AbstractController
  {
    /// <summary>
    /// Records the current position
    /// in the control sequence.
    /// </summary>
    private int currentStep;

    /// <summary>
    /// The sequence to be executed during simulation
    /// </summary>
    private readonly List<DatapathInstruction> controlSequence;

    /// <summary>
    /// Constructs a new SequenceController attacted to the
    /// specified datapath context
    /// </summary>
    /// <param name="_dp"></param>
    public SequenceController(DatapathContext datapath, string name) : base(datapath, name)
    {
      controlSequence = new List<DatapathInstruction>();
      currentStep = 0;
    }

    /// <summary>
    /// Adds a new step to the control sequence. 
    /// Parameters are ignored.
    /// </summary>
    /// <param name="ignored"></param>
    /// <param name="ignored2"></param>
    internal override void ProgramNextstep(int ignored, Symid ignored2)
    {
      DatapathInstruction instruction = new DatapathInstruction();
      controlSequence.Add(instruction);
    }

    /// <summary>
    /// Adds the execution of a signalflowgraph to the
    /// current controlstep.
    /// </summary>
    /// <param name="sfg"></param>
    internal override void AddSignalFlowGraph(Symid sfg)
    {
      System.Diagnostics.Debug.Assert(controlSequence.Count > 0, "Internal Error - unknown control step");
      // since controller is sequencer only one instruction is allowed per controlstep
      System.Diagnostics.Debug.Assert(controlSequence[controlSequence.Count - 1].InstructionCount == 0);
      
      // ok to add signal flowgraph identifier
      controlSequence[controlSequence.Count - 1].AddSignalFlowGraph(sfg);
    }

    /// <summary>
    /// Resets the controllers position in the
    /// control sequence.
    /// </summary>
    public override void Reset()
    {
      currentStep = 0;
    }

    /// <summary>
    /// Executes the current step in the
    /// control sequence and increments the
    /// current step count modulus the total
    /// number of steps
    /// </summary>
    /// <param name="RTCycle">the current cycle</param>
    public override void RunNextStep(long RTCycle)
    {
      datapathContext.CurrentControlStep = currentStep;
      controlSequence[currentStep].Select(datapathContext);

//      // for global sleep
//      if (controlSequence.Count > 1)
//        Simulation.sleep.CannotSleep();

//    if (tracer.find(currentstep) != tracer.end())
//    {
//      cout << "Sequencer step " << currentstep << "\n";
//    }

      currentStep = (currentStep + 1) % (controlSequence.Count);
    }
  }
}